home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok77.lha / IFFlib / IFFlib.lha / ShowIFF / ShowIFF.c < prev    next >
C/C++ Source or Header  |  1992-06-14  |  26KB  |  854 lines

  1. /****************************************************************************
  2. **                                                                         **
  3. **  ShowIFF - a comfortable IFF picture viewer for CLI and Workbench       **
  4. **                               by                                        **
  5. **  Christian A. Weber, Bruggerweg 2, CH-8037 Zürich, Switzerland          **
  6. **                                                                         **
  7. **  INTERNET: weber@amiga.physik.unizh.ch                                  **
  8. **  UUCP:     cbmehq!cbmswi!mighty!chris@cbmvax.commodore.com              **
  9. **                                                                         **
  10. **  For documentation, refer to the file "ShowIFF.doc".                    **
  11. **                                                                         **
  12. **  All known formats (including Overscan, HAM, Halfbrite, SHAM) are       **
  13. **  supported. If a picture is larger than the screen, you may use the     **
  14. **  mouse to scroll around (If you have enough CHIP memory...)             **
  15. **                                                                         **
  16. **  Any suggestions, donations or bug reports are welcome.                 **
  17. **                                                                         **
  18. *****************************************************************************
  19. **                                                                         **
  20. **  This program is in the Public Domain. Use it at your own risk.         **
  21. **                                                                         **
  22. **  Requirements:  - arp.library V39+                                      **
  23. **                 - iff.library V19+                                      **
  24. **                                                                         **
  25. **  To compile:    - Lattice C compiler V5.04 or above (use 32bit ints)    **
  26. **                 - The file 'arpstartup.o' (My ARP startup module)       **
  27. **                 - The file 'arpglue.lib' for Printf etc.                **
  28. **                                                                         **
  29. *****************************************************************************
  30. **                                                                         **
  31. **    Modification History:                                                **
  32. **    --------------------                                                 **
  33. **                                                                         **
  34. **    15-Oct-87  CHW  V1.0   Created this file!                            **
  35. **    30-Jun-88  CHW  V1.4   Directory scan fixed for FFS, cleaned up      **
  36. **    16-Nov-88  CHW  V1.5   Overscan implemented                          **
  37. **    28-Nov-88  CHW  V1.6   Minimal screen size is now 64x64 pixels       **
  38. **    02-Jan-89  CHW  V1.7   Double-buffering implemented                  **
  39. **    25-Sep-89  CHW  V2.01  Changed to Lattice C and ARP library          **
  40. **    27-Sep-89  CHW  V2.02  Screen scrolling implemented                  **
  41. **    22-Nov-89  CHW  V2.03  Rejects Non-ILBM files correctly              **
  42. **    21-Feb-90  CHW  V2.04  'NoMemForGfx' bug fixed, overscan fixed       **
  43. **    28-Feb-90  CHW  V2.10  SHAM support code added                       **
  44. **    14-Mar-90  CHW  V2.11  Memory fragmentation workaround, cleanup      **
  45. **    08-Apr-90  CHW  V2.12  Pics with more than 6 planes don't guru       **
  46. **    22-Apr-90  CHW  V2.14  New startup code, WB cleanup works now.       **
  47. **    16-Jul-90  CHW  V2.15  Works now properly with MoreRows & OS 2.0     **
  48. **    16-Sep-90  CHW  V2.16  Scrolling SHAM pictures implemented           **
  49. **    03-Oct-90  CHW  V2.17  MaxX0 divided by 2 because of a 2.0 bug       **
  50. **    30-Oct-90  MAB  V2.20  ShowIFF can be turned into an appicon         **
  51. **    11-Jan-91  CHW  V2.21  SHAM color errors fixed                       **
  52. **    11-Jan-91  CHW  V2.22  AppIcon image/pos are taken from .info file   **
  53. **    13-Jan-91  CHW  V2.23  COMMAND mode added, overscan bug fixed (?)    **
  54. **    14-Jan-91  CHW  V2.24  Icon tooltypes added, code moved around       **
  55. **    24-Jan-91  CHW  V2.25  Minor bug fixes                               **
  56. **    03-May-91  CHW  V2.26  Vertical centering and NOCENTER option added  **
  57. **    23-May-91  CHW  V2.27  Pointer option added                          **
  58. **    27-May-91  CHW  V2.28  True Color Table fixed and extended           **
  59. **    23-Jun-91  CHW  V2.29  AppIcon's image can be specified (ICON=...)   **
  60. **    23-Apr-92  CHW  V2.30  RasInfo-bug workaround only under V36-38      **
  61. **                                                                         **
  62. ****************************************************************************/
  63.  
  64. #define APPICON_MODE    /* This works only with the 2.0 include files */
  65.  
  66. #include <proto/exec.h>
  67. #include <exec/memory.h>
  68. #include <proto/graphics.h>
  69. #include <proto/intuition.h>
  70. #include <graphics/gfxbase.h>
  71. #include <graphics/gfxmacros.h>
  72. #include <arp/arpbase.h>
  73. #include <libraries/dosextens.h>
  74. #include <hardware/custom.h>
  75. #include <workbench/startup.h>
  76. #include <string.h>
  77. #include <libraries/iff.h>                /* Not an official CBM file */
  78.  
  79. #ifdef APPICON_MODE
  80. #include <proto/icon.h>
  81. #include <proto/wb.h>
  82. #endif
  83.  
  84. #define VERS    "ShowIFF 2.30"
  85. #define VSTRING    VERS " (23.4.92) by Christian A. Weber"
  86.  
  87. #define MIN(a,b) ((a)<(b)?(a):(b))
  88. #define MAX(a,b) ((a)>(b)?(a):(b))
  89. #define reg register                    /* My favorite alias :-) */
  90.  
  91. #define ARG_PATTERN        0                /* Argument numbers for GADS() */
  92. #define ARG_ALL            1
  93. #define ARG_LOOP        2
  94. #define ARG_DELAY        3
  95. #define ARG_NOBREAK        4
  96. #define ARG_NOCENTER    5
  97. #define ARG_NOOVERSCAN    6
  98. #define ARG_POINTER        7
  99. #define ARG_COMMAND        8
  100. #define ARG_INVALID        9
  101.  
  102. #define OPTIONSTOOLTYPE        "OPTIONS"
  103. #define ICONTOOLTYPE        "ICON"
  104. #define XPOSTOOLTYPE        "ICONXPOS"
  105. #define YPOSTOOLTYPE        "ICONYPOS"
  106. #define ICONNAMETOOLTYPE    "ICONNAME"
  107. #define APPICONPORTNAME        "ShowIFF-AppIcon"
  108. #define DEFAULTAPPICONNAME    "IFF Picture Viewer"
  109.  
  110. #define PICF_DYNA 1
  111.  
  112. /*** External references ***/
  113.  
  114. extern void exit(LONG);                    /* My startup code's exit function */
  115. extern struct Process *ProcessBase;        /* Pointer to our process */
  116. extern struct Library *ArpBase;            /* Also used for DOS functions */
  117. extern struct Custom __far custom;        /* For SHAM/DYNA copper list */
  118. extern BYTE NewOS;                        /* 0 if Kick1.2/1.3, >0 if Kick2.x */
  119.  
  120.  
  121. /*** Global definitions ***/
  122.  
  123. char VersionString[] =
  124.     "\0$VER: " VSTRING "\n\r";
  125.  
  126. char WindowTitle[] =
  127.     "CON:0/24/640/82/" VSTRING;
  128.  
  129. char CLI_Template[] =
  130.     "Patterns/...,ALL/s,L=LOOP/s,D=DELAY/k,NB=NOBREAK/s,NC=NOCENTER/s,NO=NOOVERSCAN/s,POINTER/s,COMMAND/k";
  131.  
  132. char CLI_Help[] =
  133.     VSTRING "\n"
  134.     "Usage: ShowIFF [files or patterns] [ALL] [LOOP] [DELAY delay] [NOBREAK]\n"
  135.     "\t\t[NOCENTER] [NOOVERSCAN] [POINTER] [COMMAND \"Command %s args\"]";
  136.  
  137. char StdWindowName[] = "NIL:";            /* Standard Workbench window name */
  138. struct Library *IconBase,*IFFBase;        /* Some libraries we use */
  139. char *argv[ARG_INVALID+1];                /* Arguments, filled in by GADS() */
  140. BPTR wbwindow;                            /* Output window for Workbench mode */
  141. struct DiskObject *dobj;                /* Our icon */
  142. LONG wbdelay=3145728;                    /* keep window open for 3 seconds */
  143. IFFFILE ifffile;                        /* Pointer to our IFF file */
  144. LONG delay=1000000;                        /* Time (in seconds) for each picture */
  145. WORD *emptysprite;                        /* ShowIFF's mouse pointer sprite */
  146.  
  147. struct Picture
  148. {
  149.     struct Screen        *Screen;        /* The picture's screen */
  150.     struct Window        *Window;        /* Window for mouse handling */
  151.     struct BitMap        BitMap;            /* CustomBitMap, can be larger than screen */
  152.     PLANEPTR            MorePlanes[16];    /* Extend bitmap to 24 planes */
  153.     UWORD                *SHAMColors;    /* Ptr to SHAM color table array or NULL */
  154.     WORD                Y0;                /* Beginning of picture relative to screen */
  155.     WORD                MaxX0,MaxY0;    /* Scrolling limits */
  156.     UWORD                ColorCount;        /* Number of colors in color palette */
  157.     UWORD                ColorTab[256];    /* The picture's color table */
  158.     UBYTE                Flags;
  159. } pic1,pic2;                            /* 2 pictures for double-buffering */
  160.  
  161. struct SHAMChunk
  162. {
  163.     struct Chunk    Chunk;
  164.     UWORD            Version;
  165.     UWORD            Colors[1];            /* open array */
  166. };
  167.  
  168. /***************************************************************************/
  169. /* Free all planes of a bitmap */
  170.  
  171. void MyFreeBitMap(reg struct BitMap *bm)
  172. {
  173.     reg LONG planesize=bm->BytesPerRow*bm->Rows,i;
  174.  
  175.     for(i=0; i<bm->Depth; ++i)
  176.         if(bm->Planes[i])
  177.         {
  178.             FreeMem(bm->Planes[i],planesize);
  179.             bm->Planes[i]=0;
  180.         }
  181. }
  182.  
  183. /***************************************************************************/
  184. /* Initialize a BitMap structure and allocate CHIP memory for the planes */
  185.  
  186. BOOL MyAllocBitMap(reg struct BitMap *bm,LONG d,LONG w,LONG h)
  187. {
  188.     reg LONG planesize,i;
  189.  
  190.     InitBitMap(bm,d,w,h);
  191.     planesize=bm->BytesPerRow*bm->Rows;
  192.  
  193.     for(i=0; i<d; ++i)
  194.         if(!(bm->Planes[i]=AllocMem(planesize,MEMF_CHIP|MEMF_CLEAR)))
  195.         {
  196.             MyFreeBitMap(bm); return FALSE;
  197.         }
  198.     return TRUE;
  199. }
  200.  
  201. /***************************************************************************/
  202. /* Adjust the X/Y position of a screen for correct overscan display */
  203.  
  204. void SetOverscan(reg struct Screen *screen)
  205. {
  206.     reg x=GfxBase->NormalDisplayColumns,y=GfxBase->NormalDisplayRows;
  207.  
  208.     if(!(screen->ViewPort.Modes & HIRES)) x >>= 1;
  209.     if(  screen->ViewPort.Modes & LACE  ) y <<= 1;
  210.  
  211.     x = (x-screen->Width ) >> 1;
  212.     y = (y-screen->Height) >> 1; if(y>0) y=0;
  213.  
  214.     /* Avoid garbled pictures: */
  215.     if(GfxBase->ActiView->DyOffset+y < 0) y = 0-GfxBase->ActiView->DyOffset;
  216.  
  217.     /* Correct overscan HAM color distortions: */
  218.     if(screen->ViewPort.Modes & HAM)
  219.     {
  220.         if(GfxBase->ActiView->DxOffset+x < 96)
  221.             x=96-GfxBase->ActiView->DxOffset;
  222.     }
  223.  
  224. #if 0
  225.     Printf("S(%ld,%ld) O(%ld,%ld) ",screen->Width,screen->Height,x,y);
  226. #endif
  227.  
  228. //    if(NewOS) MoveScreen(screen,x,y);
  229. //    else
  230.     {
  231.         screen->ViewPort.DxOffset = x; screen->ViewPort.DyOffset = y;
  232.         MakeScreen(screen); RethinkDisplay();
  233.     }
  234. }
  235.  
  236. /***************************************************************************/
  237. /* Create intermediate SHAM copper list if this is an SHAM picture */
  238.  
  239. void MakeSHAMCopList(struct Picture *pic)
  240. {
  241.     reg struct UCopList *ucop;
  242.  
  243.     if(!pic->SHAMColors) return;    /* Not an SHAM picture, no work to do */
  244.  
  245.     if(ucop=AllocMem(sizeof(struct UCopList),MEMF_CLEAR))
  246.     {
  247.         reg struct Screen *s=pic->Screen;
  248.         reg LONG i,j,step=(s->ViewPort.Modes&LACE) ? 2:1;
  249.         reg UWORD copx=GfxBase->ActiView->DxOffset+s->Width;
  250.         reg UWORD y0=s->ViewPort.RasInfo->RyOffset;
  251.  
  252.         if(pic->Flags & PICF_DYNA) step=1;
  253.         for(i=1; i<(s->Height/step); ++i)
  254.         {
  255.             CWAIT(ucop,pic->Y0+(i-1)*step,(UWORD)((copx>>1)%(UWORD)228))
  256.             for(j=1; j<16; ++j)
  257.                 CMOVE(ucop,custom.color[j],pic->SHAMColors[16*(y0+i)+j])
  258.         }
  259.         CEND(ucop)
  260. //        FreeVPortCopLists(&s->ViewPort);
  261.         s->ViewPort.UCopIns = ucop;
  262.         pic->SHAMColors[16*y0]=pic->ColorTab[0];    /* Fix some weird SHAM pics */
  263.         LoadRGB4(&s->ViewPort,&pic->SHAMColors[16*y0],16);
  264.     }
  265. }
  266.  
  267. /***************************************************************************/
  268. /* Free a picture (that is a window, screen and a custom BitMap) */
  269.  
  270. void ClosePicture(reg struct Picture *pic)
  271. {
  272.     if(pic->Window)
  273.     {
  274.         ScreenToBack(pic->Screen);
  275.         if(!argv[ARG_POINTER]) ClearPointer(pic->Window);
  276.         CloseWindow(pic->Window);
  277.         pic->Window=0;
  278.     }
  279.  
  280.     if(pic->Screen)
  281.     {
  282.         CloseScreen(pic->Screen);
  283.         pic->Screen=0;
  284.     }
  285.  
  286.     MyFreeBitMap(&pic->BitMap);
  287.     RemakeDisplay();    /* remake copperlist to increase MEMF_LARGEST */
  288. }
  289.  
  290. /***************************************************************************/
  291. /* Allocate a picture (Allocate custom BitMap, open screen and window) */
  292.  
  293. BOOL OpenPicture(reg struct Picture *pic,reg struct BitMapHeader *bmhd)
  294. {
  295.     struct NewScreen ns;
  296.     struct NewWindow nw;
  297.  
  298.     ClosePicture(pic);
  299.  
  300.     memset(&ns,0,sizeof(ns));
  301.     memset(&nw,0,sizeof(nw));
  302.     memset(pic,0,sizeof(*pic));
  303.  
  304.     ns.Width        = GfxBase->NormalDisplayColumns;
  305.     ns.Height       = GfxBase->NormalDisplayRows;
  306.     ns.Depth        = MAX(1,bmhd->nPlanes);    if(ns.Depth>6) ns.Depth=4;
  307.     ns.ViewModes    = (UWORD)GetViewModes(ifffile);
  308.     ns.Type         = CUSTOMSCREEN|CUSTOMBITMAP|SCREENQUIET|SCREENBEHIND;
  309.     ns.CustomBitMap = &pic->BitMap;
  310.  
  311.     if(!(ns.ViewModes & HIRES))    { ns.Width  >>= 1; }
  312.     if(  ns.ViewModes & LACE)    { ns.Height <<= 1; }
  313.  
  314.     if(argv[ARG_NOCENTER])    ns.Height = MIN(bmhd->h,ns.Height);
  315.     else                    ns.Width  = MIN(bmhd->w,ns.Width);
  316.  
  317.     ns.Width  = MAX(128,ns.Width);
  318.     ns.Height = MAX(128,ns.Height);
  319.  
  320.     if(!argv[ARG_NOOVERSCAN])
  321.     {
  322.         if((bmhd->w > ns.Width) && (bmhd->w <= (ns.ViewModes&HIRES ? 768:384)))
  323.             ns.Width = bmhd->w;
  324.  
  325.         if((bmhd->h>ns.Height) && (bmhd->h<=(ns.Height+(ns.ViewModes&LACE?80:40))))
  326.             ns.Height = bmhd->h;
  327.     }
  328.  
  329.     if(MyAllocBitMap(&pic->BitMap,MAX(bmhd->nPlanes,ns.Depth),
  330.                 MAX(bmhd->w,ns.Width),MAX(bmhd->h,ns.Height)))
  331.     {
  332.         reg olddepth      = pic->BitMap.Depth;
  333.         pic->BitMap.Depth = ns.Depth;
  334.         pic->Screen       = OpenScreen(&ns);
  335.         pic->BitMap.Depth = olddepth;
  336.  
  337.         if(nw.Screen=pic->Screen)
  338.         {
  339.             nw.Width      = ns.Width;
  340.             nw.Height     = ns.Height;
  341.             nw.IDCMPFlags = MOUSEBUTTONS|MOUSEMOVE|DELTAMOVE|VANILLAKEY;
  342.             nw.Flags      = BACKDROP|BORDERLESS|ACTIVATE|SIMPLE_REFRESH
  343.                                 |NOCAREREFRESH|REPORTMOUSE|RMBTRAP;
  344.             nw.Type       = CUSTOMSCREEN;
  345.  
  346.             if(pic->Window=OpenWindow(&nw))
  347.             {
  348.                 pic->Y0=(ns.Height-bmhd->h)>>1; if(pic->Y0<0) pic->Y0=0;
  349.  
  350.                 pic->MaxX0 = bmhd->w-ns.Width;
  351.                 pic->MaxY0 = bmhd->h-ns.Height;
  352.  
  353.                 /*
  354.                 **    In 2.0 there's this RasInfo scrolling bug, they
  355.                 **    said they'll fix it for newer ROMs, so we'll do an
  356.                 **    explicit version check
  357.                 */
  358.                 if(ns.ViewModes & HIRES)
  359.                 {
  360.                     if(    (GfxBase->LibNode.lib_Version >= 36)
  361.                     &&    (GfxBase->LibNode.lib_Version <= 38))
  362.                      pic->MaxX0 >>= 1;
  363.                 }
  364.  
  365.                 if(!argv[ARG_POINTER])
  366.                     SetPointer(pic->Window,emptysprite,1L,16L,0L,0L);
  367.  
  368.                 if(bmhd->nPlanes == 24)
  369.                 {
  370.                     static UWORD truecoltab[32] =
  371.                     {
  372.                         0x000,0x00C,0x0C0,0x0CC,0xC00,0xC0C,0xCC0,0xCCC,
  373.                         0x080,0x08C,0x0F0,0x0FC,0xC80,0xC8C,0xCF0,0xCFC,
  374.                         0x800,0x80C,0x8C0,0x8CC,0xF00,0xF0C,0xFC0,0xFCC,
  375.                         0x880,0x88C,0x8F0,0x8FC,0xF80,0xF8C,0xFF0,0xFFC
  376.                     };
  377.                     memcpy(pic->ColorTab,truecoltab,sizeof(truecoltab));
  378.                     pic->Screen->BitMap.Planes[0]=pic->BitMap.Planes[23];    /* B7 */
  379.                     pic->Screen->BitMap.Planes[1]=pic->BitMap.Planes[15];    /* G7 */
  380.                     pic->Screen->BitMap.Planes[2]=pic->BitMap.Planes[7];    /* R7 */
  381.                     pic->Screen->BitMap.Planes[3]=pic->BitMap.Planes[14];    /* G6 */
  382.                     pic->Screen->BitMap.Planes[4]=pic->BitMap.Planes[6];    /* R7 */
  383.                     pic->ColorCount = (ns.ViewModes&HIRES) ? 16:32;
  384.                 }
  385.                 else
  386.                 {
  387.                     if(!(pic->ColorCount=GetColorTab(ifffile,pic->ColorTab)))
  388.                     {
  389.                         /* Provide default colors for pictures without a CMAP */
  390.                         pic->ColorCount=2;
  391.                         pic->ColorTab[0]=0xeca; pic->ColorTab[1]=0x000;
  392.                     }
  393.                 }
  394.  
  395.                 if(pic->ColorCount>32) pic->ColorCount = 32; /* Old DigiView */
  396.                 LoadRGB4(&pic->Screen->ViewPort,pic->ColorTab,pic->ColorCount);
  397.                 SetOverscan(pic->Screen);
  398.                 return TRUE;
  399.             }
  400.         }
  401.     }
  402.     ClosePicture(pic);
  403.     return FALSE;
  404. }
  405.  
  406. /***************************************************************************/
  407. /* Close all resources and exit to CLI/WorkBench */
  408.  
  409. void Fail(reg char *reason)
  410. {
  411.     Puts(reason);
  412.  
  413.     ClosePicture(&pic1); ClosePicture(&pic2);
  414.     if(ifffile)    CloseIFF(ifffile);
  415.     if(dobj)    FreeDiskObject(dobj);
  416.  
  417.     if(wbwindow)
  418.     {
  419.         WaitForChar(wbwindow,wbdelay);    /* Let them see our text */
  420.         Close(wbwindow);
  421.     }
  422.  
  423.     if(IFFBase)        CloseLibrary(IFFBase);
  424.     if(IconBase)    CloseLibrary(IconBase);
  425.  
  426.     exit(0L);    /* Back to the startup code (important for Workbench) */
  427. }
  428.  
  429. /***************************************************************************/
  430. /* That's the big one! Load & display a picture (with mouse-scrolling),
  431.    return FALSE if user presses the RMB (abort), else return TRUE */
  432.  
  433. BOOL ShowPicture(reg char *name)
  434. {
  435.     reg BOOL cont=TRUE;
  436.     reg struct BitMapHeader *bmhd;
  437.  
  438.     if(!strcmp(name+strlen(name)-5,".info")) return TRUE;    /* Skip icons */
  439.     Printf("%s ... ",name);
  440.  
  441.     if(ifffile) CloseIFF(ifffile);
  442.  
  443.     if(!(ifffile=OpenIFF(name)))
  444.     {
  445.         Puts("- not an IFF file!");
  446.         return TRUE;
  447.     }
  448.  
  449.     if(*(((ULONG *)ifffile)+2) != ID_ILBM)
  450.     {
  451.         Puts("- not an ILBM file!");
  452.         return TRUE;
  453.     }
  454.  
  455.     if(!(bmhd=GetBMHD(ifffile)))
  456.     {
  457.         Printf("- Mangled IFF file (Error %ld)\n",IFFError());
  458.         return TRUE;
  459.     }
  460.  
  461.     Printf("%ld x %ld x %ld ",bmhd->w,bmhd->h,bmhd->nPlanes);
  462. retry:
  463.     if(OpenPicture(&pic1,bmhd))
  464.     {
  465.         if(DecodePic(ifffile,&pic1.BitMap))
  466.         {
  467.             reg struct SHAMChunk *sham;
  468.             reg LONG i;
  469.             reg WORD xoff=0,yoff=0;
  470.  
  471.             if(pic1.Y0)
  472.             {
  473.                 struct Screen *s=pic1.Screen;
  474.                 ScrollRaster(&s->RastPort,0,-pic1.Y0,0,0,
  475.                     s->BitMap.BytesPerRow<<3,s->BitMap.Rows);
  476.             }
  477.  
  478.             if(sham=FindChunk(ifffile,ID_SHAM))
  479.             {
  480.                 Printf("SHAM ");
  481.                 if(sham->Version == 0)
  482.                 {
  483.                     pic1.SHAMColors = sham->Colors;
  484.                 }
  485.                 else Printf("Unsupported mode: %ld ",(LONG)sham->Version);
  486.  
  487.                 MakeSHAMCopList(&pic1);
  488.             }
  489.  
  490.             if(sham=FindChunk(ifffile,ID_CTBL))
  491.             {
  492.                 Printf("DYNA ");
  493.                 pic1.SHAMColors = &sham->Version;    /* DYNA has no version */
  494.                 pic1.Flags |= PICF_DYNA;
  495.                 MakeSHAMCopList(&pic1);
  496.             }
  497.  
  498.             ScreenToFront(pic1.Screen);
  499.             ClosePicture(&pic2);
  500.             for(i=delay*50L; i>=0; --i)
  501.             {
  502.                 reg struct IntuiMessage *msg;
  503.  
  504.                 WaitTOF();
  505.                 while(msg=(struct IntuiMessage *)GetMsg(pic1.Window->UserPort))
  506.                 {
  507. newmsg:                switch(msg->Class)
  508.                     {
  509.                     case MOUSEMOVE:
  510.  
  511.                         xoff+=msg->MouseX;
  512.                         yoff+=msg->MouseY;
  513.                         if(xoff>pic1.MaxX0) xoff=pic1.MaxX0;
  514.                         if(xoff<0) xoff=0;
  515.                         if(yoff>pic1.MaxY0) yoff=pic1.MaxY0;
  516.                         if(yoff<0) yoff=0;
  517.                         pic1.Screen->ViewPort.RasInfo->RxOffset=xoff;
  518.                         pic1.Screen->ViewPort.RasInfo->RyOffset=yoff;
  519.                         if(pic1.SHAMColors)
  520.                         {
  521.                             reg struct IntuiMessage *m2;
  522.                             MakeSHAMCopList(&pic1);
  523.                             while(m2=GetMsg(pic1.Window->UserPort))
  524.                             {
  525.                                 ReplyMsg(msg); msg=m2;
  526.                                 if(msg->Class == MOUSEMOVE)
  527.                                 {
  528.                                     xoff+=msg->MouseX;
  529.                                     yoff+=msg->MouseY;
  530.                                 }
  531.                                 else goto newmsg;
  532.                             }
  533.                         }
  534.                         /* ScrollVPort(&pic1.Screen->ViewPort); */
  535.                         MakeScreen(pic1.Screen); RethinkDisplay();
  536.                         break;
  537.  
  538.                     case VANILLAKEY:
  539.                         if(msg->Code == 'c') if(argv[ARG_COMMAND])
  540.                         {
  541.                             char buf[200];
  542.                             SPrintf(buf,argv[ARG_COMMAND],name,name);
  543.                             Execute(buf,NULL,Output());
  544.                         }
  545.                         break;
  546.  
  547.                     case MOUSEBUTTONS:
  548.                         if(!argv[ARG_NOBREAK])
  549.                         {
  550.                             if(msg->Code == MENUDOWN)    goto usrbreak;
  551.                             if(msg->Code == SELECTDOWN)    goto showend;
  552.                         }
  553.                         break;
  554.                     }
  555.                     ReplyMsg(msg);
  556.                 }
  557.                 if(!argv[ARG_NOBREAK]) if(CheckAbort(NULL))
  558.                 {
  559. usrbreak:            Puts("***BREAK"); cont=FALSE; goto showend2;
  560.                 }
  561.             }
  562. showend:    Puts("- Done");
  563. showend2:    pic2=pic1; memset(&pic1,0,sizeof(pic1));
  564.         }
  565.         else
  566.         {
  567.             ClosePicture(&pic1);
  568.             Printf("- Decode error: %ld\n",IFFError());
  569.         }
  570.     }
  571.     else if(pic2.Window)
  572.     {
  573.         ClosePicture(&pic2); goto retry;
  574.     }
  575.     else Puts("- Can't open screen!");
  576.     return cont;
  577. }
  578.  
  579. /***************************************************************************/
  580. /* Expand a pattern and call ShowPicture() for each matching file,
  581.    return FALSE if the user presses ^C or ShowPicture() returns FALSE */
  582.  
  583. BOOL ShowPattern(char *pathname)
  584. {
  585.     char buf[256];
  586.     reg BPTR file;
  587.     reg BOOL cont=TRUE;
  588.  
  589.     if(PreParse(pathname,buf))    /* TRUE if name contains any wildcards */
  590.     {
  591.         reg struct {
  592.             struct AnchorPath APath;
  593.             char   FullPath[255];        /* cheap way to extend ap_Buf[] */
  594.         } *myanchor;
  595. iswild:
  596.         if(myanchor=ArpAlloc(sizeof(*myanchor)))
  597.         {
  598.             reg BOOL showit=TRUE;
  599.             reg LONG error;
  600.  
  601.             myanchor->APath.ap_StrLen = 255;    /* Want full path built */
  602.             myanchor->APath.ap_Flags = APF_DOWILD;
  603.             myanchor->APath.ap_BreakBits=SIGBREAKF_CTRL_C;
  604.  
  605.             error=FindFirst(pathname,&myanchor->APath);
  606.             while(!error)
  607.             {
  608.                 /* +1 because of a lattice bug */
  609.                 if(SetSignal(0L,SIGBREAKF_CTRL_E+1) & SIGBREAKF_CTRL_E)
  610.                 {
  611.                     Puts("***DIR BREAK"); showit=FALSE;
  612.                     /* myanchor->APath.ap_Flags &= ~APF_DODIR; */
  613.                 }
  614.  
  615.                 if(myanchor->APath.ap_Info.fib_DirEntryType>=0)    /* Dir */
  616.                 {
  617.                     if(argv[ARG_ALL])
  618.                     {
  619.                         if(!(myanchor->APath.ap_Flags & APF_DIDDIR))
  620.                         {
  621.                             myanchor->APath.ap_Flags |= APF_DODIR;
  622.                             showit=TRUE;
  623.                         }
  624.                         myanchor->APath.ap_Flags &= ~APF_DIDDIR;
  625.                     }
  626.                 }
  627.                 else if(showit) if(!ShowPicture(myanchor->APath.ap_Buf))
  628.                 {
  629.                     cont = FALSE; break;
  630.                 }
  631.                 error=FindNext(&myanchor->APath);
  632.             }
  633.  
  634.             FreeAnchorChain(&myanchor->APath);
  635.  
  636.             switch(error)
  637.             {
  638.                 case 0:                            break;
  639.  
  640.                 case ERROR_BREAK:                Puts("***BREAK"); cont=FALSE; break;
  641.  
  642.                 case ERROR_OBJECT_NOT_FOUND:    Puts("File not found."); break;
  643.  
  644.                 case ERROR_BUFFER_OVERFLOW:        Puts("Path too long!"); break;
  645.  
  646.                 case ERROR_NO_MORE_ENTRIES:        break;    /* Normal termination */
  647.  
  648.                 default:    Printf("IO error %ld!\n",error); break;
  649.             }
  650.         }
  651.         else Fail("No mem for anchor!");
  652.     }
  653.     else if(file=Open(pathname,MODE_OLDFILE))    /* Just one file ? */
  654.     {
  655.         Close(file); return ShowPicture(pathname);
  656.     }
  657.     else    /* No wildcards, and not a file: it's a device or a directory */
  658.     {
  659.         strcpy(buf,pathname); TackOn(pathname=buf,"*");
  660.         goto iswild;    /* Not really elegant, but it works */
  661.     }
  662.  
  663.     return cont;
  664. }
  665.  
  666. #ifdef APPICON_MODE
  667. /***************************************************************************/
  668. /* Started without arguments: create or delete our appicon */
  669.  
  670. void AppIconStuff(void)
  671. {
  672.     struct Library *WorkbenchBase;
  673.     struct MsgPort *msgport;
  674.       struct AppIcon *ai;
  675.     struct AppMessage *amsg;
  676.  
  677.     if(!(WorkbenchBase = OpenLibrary(WORKBENCH_NAME,36))) return;
  678.  
  679.     if(msgport=FindPort(APPICONPORTNAME))    /* Already running ? */
  680.     {
  681.         Signal(msgport->mp_SigTask,SIGBREAKF_CTRL_C);    /* Kill it */
  682.     }    
  683.     else if(msgport = CreatePort(APPICONPORTNAME,0)) 
  684.     {
  685.         char *tooltype;
  686.         struct DiskObject *appdobj=NULL;
  687.  
  688.         if(tooltype=FindToolType(dobj->do_ToolTypes,ICONTOOLTYPE))
  689.             appdobj=GetDiskObject(tooltype);
  690.         if(!appdobj) appdobj=dobj;
  691.  
  692.         if(tooltype=FindToolType(dobj->do_ToolTypes,XPOSTOOLTYPE))
  693.             appdobj->do_CurrentX = Atol(tooltype);
  694.         else
  695.             appdobj->do_CurrentX = NO_ICON_POSITION;
  696.  
  697.         if(tooltype=FindToolType(dobj->do_ToolTypes,YPOSTOOLTYPE))
  698.             appdobj->do_CurrentY = Atol(tooltype);
  699.         else
  700.             appdobj->do_CurrentY = NO_ICON_POSITION;
  701.  
  702.         if(!(tooltype=FindToolType(dobj->do_ToolTypes,ICONNAMETOOLTYPE)))
  703.             tooltype = DEFAULTAPPICONNAME;
  704.  
  705.         if(ai = AddAppIconA(0,0,tooltype,msgport,NULL,appdobj,NULL)) 
  706.         {
  707.             while(!(Wait(1L << msgport->mp_SigBit | SIGBREAKF_CTRL_C)
  708.                          & SIGBREAKF_CTRL_C))
  709.             {
  710.                 reg BPTR oldcos;
  711.  
  712.                 if(wbwindow=Open(WindowTitle,MODE_OLDFILE))
  713.                 {
  714.                     oldcos = ProcessBase->pr_COS;
  715.                     ProcessBase->pr_COS = wbwindow;
  716.                 }
  717.  
  718.                 while(amsg = GetMsg(msgport)) 
  719.                 {
  720.                     reg i,cont=TRUE;
  721.                     struct WBArg *arg = amsg->am_ArgList;
  722.                       for(i=0; (i < amsg->am_NumArgs) && cont; i++,arg++)
  723.                       {
  724.                         reg BPTR oldcd=0;
  725.                         if(arg->wa_Lock) oldcd=CurrentDir(arg->wa_Lock);
  726.                         else DisplayBeep(NULL);
  727.                         cont=ShowPattern(arg->wa_Name&&*arg->wa_Name ? arg->wa_Name:"*");
  728.                         if(oldcd) CurrentDir(oldcd);
  729.                     }
  730.                     ReplyMsg(amsg);
  731.                 }
  732.                 ClosePicture(&pic2);         /* Close last screen */
  733.                 if(wbwindow)
  734.                 {
  735.                     WaitForChar(wbwindow,2097152);    /* Wait 2 seconds */
  736.                     ProcessBase->pr_COS = oldcos;
  737.                     Close(wbwindow); wbwindow=0;
  738.                     SetSignal(0,SIGBREAKF_CTRL_C);    /* Clear break sig */
  739.                 }
  740.             }
  741.             RemoveAppIcon(ai);
  742.         }
  743.  
  744.         if(appdobj != dobj) FreeDiskObject(appdobj);
  745.  
  746.         /* Make sure there are no more messages pending */
  747.         while(amsg = GetMsg(msgport)) ReplyMsg(amsg);
  748.         DeletePort(msgport);
  749.     }
  750.     CloseLibrary(WorkbenchBase);
  751. }
  752. #endif
  753.  
  754. /***************************************************************************/
  755. /* Main program: parse the command line or WorkBench-args */
  756.  
  757. void ARPMain(LONG arglen,reg char *argline)
  758. {
  759.        if(!(IconBase = OpenLibrary("icon.library",0)))    Fail("No icon.library!");
  760.     if(!(IFFBase  = OpenLibrary(IFFNAME,0L)))        Fail("No iff.library!");
  761.  
  762.     if(IFFBase->lib_Version < IFFVERSION)
  763.         Puts("WARNING: you have an old version of iff.library!");
  764.  
  765.     emptysprite=ArpAllocMem(20L,MEMF_CHIP|MEMF_CLEAR);
  766.  
  767.     if(arglen)        /* From CLI */
  768.     {
  769.         if(*argline != '\n')
  770.         {
  771.             if(GADS(argline,strlen(argline),CLI_Help,argv,CLI_Template)>0)
  772.             {
  773.                 if(argv[ARG_DELAY]) delay=Atol(argv[ARG_DELAY]);
  774.                 do
  775.                 {
  776.                     reg char **pattern=(char **)argv[ARG_PATTERN];
  777.                     if(*pattern)
  778.                     {
  779.                         while(*pattern) if(!ShowPattern(*pattern++)) goto done;
  780.                     }
  781.                     else ShowPattern("*");
  782.                 } while(argv[ARG_LOOP]);
  783. done: ;
  784.             }
  785.             else Fail(CLI_Help);
  786.         }
  787.         else Fail(CLI_Help);
  788.     }
  789.     else    /* Called from Workbench */
  790.     {
  791.         reg struct WBStartup *startup = (struct WBStartup *)argline;
  792.  
  793.         argv[ARG_ALL]        = (void *)TRUE;            /* Set defaults */
  794. //        argv[ARG_LOOP]       = (void *)FALSE;
  795. //        argv[ARG_NOBREAK]    = (void *)FALSE;
  796. //        argv[ARG_NOOVERSCAN] = (void *)FALSE;
  797.  
  798.         if(dobj = GetDiskObject(startup->sm_ArgList->wa_Name))
  799.         {
  800.             reg char *tooltype;
  801.             if(tooltype=FindToolType(dobj->do_ToolTypes,OPTIONSTOOLTYPE))
  802.             {
  803.                 GADS(tooltype,strlen(tooltype),NULL,argv,CLI_Template);
  804.                 if(argv[ARG_DELAY]) delay=Atol(argv[ARG_DELAY]);
  805.             }
  806.         }
  807.         if(startup->sm_NumArgs > 1)    /* Started with some arguments */
  808.         {
  809.             reg i;
  810.             struct WBArg *arg = startup->sm_ArgList;
  811.  
  812.             if(wbwindow=Open(WindowTitle,MODE_OLDFILE))        /* Open window */
  813.                 ProcessBase->pr_COS=wbwindow;
  814.  
  815.             for(i=1; i<startup->sm_NumArgs; ++i)
  816.             {
  817.                 arg++;
  818.                 if(arg->wa_Lock) CurrentDir(arg->wa_Lock);
  819.                 else Puts("Can't lock dir!");
  820.                 if(arg->wa_Name && *arg->wa_Name)
  821.                 {
  822.                     if(!ShowPattern(arg->wa_Name)) break;
  823.                 }
  824.                 else ShowPattern("*");
  825.             }
  826.         }
  827.         else    /* no arguments, just clicked */
  828. #ifdef APPICON_MODE
  829.         if(NewOS) AppIconStuff(); else
  830. #endif
  831.         {
  832.             if(wbwindow=Open(WindowTitle,MODE_OLDFILE))        /* Open window */
  833.                 ProcessBase->pr_COS=wbwindow;
  834.  
  835.             wbdelay=6291456;    /* 6 seconds delay */
  836. #ifdef GERMAN
  837.             Fail("Bitte klicken Sie alle gewünschten Bild-Dateien oder Schubladen bei ge-\n"
  838.              "drückter SHIFT-Taste an, klicken Sie danach 2x auf das ShowIFF-Piktogramm.");
  839. #else
  840.             Fail("Please select all drawers and files to view while holding\n"
  841.              "down the SHIFT key, then double-click the ShowIFF icon.");
  842. #endif
  843.         }
  844.     }
  845.     wbdelay=1048576;            /* One second delay */
  846. #ifdef GERMAN
  847.     Fail("Fertig.");
  848. #else
  849.     Fail("All done.");
  850. #endif
  851.  
  852. }
  853.  
  854.